]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
screenshot: Ensure that ShellScreenshot stays alive until the callback
authorJasper St. Pierre <jstpierre@mecheye.net>
Sun, 25 Mar 2012 14:54:08 +0000 (11:54 -0300)
committerJasper St. Pierre <jstpierre@mecheye.net>
Mon, 26 Mar 2012 15:54:07 +0000 (12:54 -0300)
We've been dangling on the edge of unsafety, unnoticed, for a little while
about the reference count safety of ShellScreenshot. GJS owns the entire
reference count, so as soon as it goes out of scope it could die, causing
GJS to try and fetch the corresponding wrapper object for a stale pointer.
We haven't seen any crashes because of luck -- SpiderMonkey tries to group
together deallocations to limit GC pauses, and there isn't really a lot
of GC pressure in the duration that a screenshot happens, so we tend to
be mostly stable. But in the case that you create a lot of objects while
a screenshot is going on, by hammering the "Print Screen" button, for
example, you can destroy the GObject before the callback finishes.

https://bugzilla.gnome.org/show_bug.cgi?id=672775

src/shell-screenshot.c

index b0dcfa38cd8d7200935f13b413460f95c7e78983..33b981e8e2ad4cf2372dd029988b400397833711 100644 (file)
@@ -65,6 +65,7 @@ on_screenshot_written (GObject *source,
                                &screenshot_data->screenshot_area);
 
   cairo_surface_destroy (screenshot_data->image);
+  g_object_unref (screenshot_data->screenshot);
   g_free (screenshot_data->filename);
   g_free (screenshot_data);
 }
@@ -262,7 +263,7 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
   ClutterActor *stage;
   _screenshot_data *data = g_new0 (_screenshot_data, 1);
 
-  data->screenshot = screenshot;
+  data->screenshot = g_object_ref (screenshot);
   data->filename = g_strdup (filename);
   data->callback = callback;
   data->include_cursor = include_cursor;
@@ -301,7 +302,7 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
   ClutterActor *stage;
   _screenshot_data *data = g_new0 (_screenshot_data, 1);
 
-  data->screenshot = screenshot;
+  data->screenshot = g_object_ref (screenshot);
   data->filename = g_strdup (filename);
   data->screenshot_area.x = x;
   data->screenshot_area.y = y;
@@ -350,7 +351,7 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
   MetaRectangle rect;
   cairo_rectangle_int_t clip;
 
-  screenshot_data->screenshot = screenshot;
+  screenshot_data->screenshot = g_object_ref (screenshot);
   screenshot_data->filename = g_strdup (filename);
   screenshot_data->callback = callback;